const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const webpack = require('webpack')
module.exports = {
  // 当前环境 生产or开发 production development
  mode: 'production',
  // 一般用于快速找到浏览器控制台打印的当前代码开发环境位置
  // 不配置的话默认是打包后的环境，不便于查找
  devtool: 'eval-cheap-source-map',
  // 入口文件
  // 单文件引入
  entry: './src/main.js', // 写相对路径
  // 多文件引入
  // entry: {
  //   main: './src/main.js',
  //   aaa: './aaa.js'
  // },
  output: {
    // 文件输出路径
    path: path.resolve(__dirname, 'dist'), // 绝对路径
    // 文件名，也能修改打包后的文件路径

    // filename: 'static/js/main.js',
    // 如果要拆分js文件，用下面这种命名方式，反之上面
    // [hash]是一旦单个文件内容发生改变，就算其余文件内容未改变，hash值也会变，文件名字也会变，浏览器也会重新加载
    // [chunkhash]文件内容未改变，hash值不会变，也就是文件名字不会变，浏览器会走缓存，无需重新
    filename: 'static/js/[name].[chunkhash:4].bundle.js',
    // 打包之前删除上次打包的文件，原理是将整个path路径的目录内容清空
    clean: true,
    // 给异步加载的文件命名,如果未写，默认按照filename配置项执行
    chunkFilename: "static/js/[name].[chunkhash:4].async.js"
  },
  // webpack优化类配置
  optimization: {
    splitChunks: {
      chunks: 'all',// 配置项有all：表示全部分离，async：表示分离异步导入，initial：分离同步导入
      // minChunks: 2, // 引入次数超过两次则分离
      // minSize: 1000, // 大于1000byte则分离
      // 以上为多文件入口时默认采取的分离规则
      // 下面为复杂业务代码时采用的分离规则，二选一
      // 下面规则适用于多入口和单入口通用规则
      cacheGroups: {
        // 把引入的第三方库单独分离打包
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          filename: 'vendor.[chunkhash:4].js', // 打包文件后的命名
          chunks: 'all',
          minChunks: 1
        },
        // 非第三方库的公用业务逻辑代码分离打包
        common: {
          filename: 'common[chunkhash:4]..js',
          chunks: 'all',
          minChunks: 2,
          minSize: 0
        }
      }
    },
    runtimeChunk: {
      // 打包时分离webpack运行代码
      name: 'runtime'
    }
  },
  // 加载器
  module: {
    rules: [
      // loader的配置
      {
        // 用来匹配css文件
        test: /\.css$/,
        // use的执行顺序是从右到左（从下到上），写loader的话不能配置
        use: [
          MiniCssExtractPlugin.loader, // 将js中的css代码打包分离出一个css文件
          // 'style-loader',// 将js中的css通过创建style标签添加到html中生效
          'css-loader' // 将css资源编译成commonjs的模块到js中
        ]
      },
      {
        // 用来匹配scss文件或者sass文件
        test: /\.s[ac]ss$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'sass-loader'// 将scss文件编译成css
        ]
      },
      {
        test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader'
        ]
      },
      {
        // 用来匹配图片文件
        test: /\.(png|jpg|gif)$/i,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            // 图片小于1kb的图片都打包成bas64
            maxSize: 1 * 1024 // 单位这里是b   1kb=1024b  1mb=1024kb
          }
        },
        generator: {
          // 自定义打包后的图片路径
          // [hash][ext][query]表示名字取hash值，ext保留后缀名，在url路径后面配的查询字符串保留
          // [hash:10]表示取前十位的hash值作为文件名
          filename: 'static/image/[hash:10][ext][query]'
        }
      },
      // 匹配svg文件
      {
        test: /\.svg$/,
        use: ['svg-inline-loader']
      }
    ],
  },
  plugins: [
    // plugin的配置
    new HtmlWebpackPlugin({
      // 引入模板html
      template: './public/index.html',
      // 打包生成的文件
      filename: 'index.html',
      // 声明打包引入的js文件引入位置，默认head
      inject: "body"
    }),
    // 将js中的css代码打包分离出一个css文件
    new MiniCssExtractPlugin({
      filename: 'static/css/[name].[chunkhash:4].bundle.css'
    }),
    // 打包分析
    new BundleAnalyzerPlugin(),
    // dll打包时间优化，提前打包第三方库
    new webpack.DllReferencePlugin({
      manifest: require(path.resolve(__dirname, 'dll', 'vendor-manifest.json'))
    })

  ],
  resolve: {
    // 路径别名
    alias: {
      "@": "/src",
      "@img": "/src/image",
      "@scss": "/src/scss",
      "@less": "/src/less"
    },
    // 配置如下代码，可引入文件时省略后缀名
    extensions: ['.js', '.css', '.less', '.scss']
  },
  devServer: {
    port: 8000, //服务器端口号
    hot: true, //开启热更新
  }
}